<?php
namespace wechat;
class Wx{
    //用户发送过来的消息属性
    protected $message;
    public function __construct()
    {
        //自动执行获取服务器上数据流里面的数据方法,将得到的数据赋值给属性
        $this->message=$this->parseAction();
    }

    /**
     * 验证连接微信服务器
     */
    public function valid(){
        if (isset($_GET['signature']) && isset($_GET['timestamp']) && isset($_GET['nonce']) && isset($_GET['echostr'])) {
            //为了和微信服务器之间建立合作关系
//将微信提供的数据接受一下（get参数）
            $signature = $_GET['signature'];
            $timestamp = $_GET['timestamp'];
            $nonce = $_GET['nonce'];
            $echostr = $_GET['echostr'];
//需要在文件中设置和在微信公众号后台一样的token值,必须要一样
            $token = 'wangxu11';
//将$timestamp,$nonce,$token放入一个数组中,然后进行字典化排序
            $arr = [$timestamp, $nonce, $token];
            sort($arr, SORT_STRING);
//将数组切割成一个字符串
            $str = implode($arr);
//对切割完成后的字符串进行加密，确保与微信方服务器提供的一致
            $string = sha1($str);
//判断是否一致
            if ($string == $signature) {
                //如果两次加密后的签名相同,代表所有参数都相同,加密方式一样,这个时候,我们需要将微信给我们的$echostr参数原样输出给它
                echo $echostr;
            }
        }
        }

    /**
     * 获取用户发送的消息（从微信服务器上获取）
     */
    public function  parseAction(){
       //获取服务器上的数据流数据
        $xml = file_get_contents('php://input');
       //判断$xml数据是否存在
        if($xml){
             //将xml数据转换成对象
            //第一个参数是要处理的数据是什么
            //第二个参数是你要转换成的对象的名称,名称一定是下面写的第二个参数的名称
         $message=simplexml_load_string($xml,'simpleXMLElement',LIBXML_NOCDATA);
            return $message;
        }
    }

    /**
     * 获取用户发送的消息
     */
    public function getMessage(){
        return $this->message;
    }

    /**
     * curl发送请求方法
     * @param $url  请求地址
     * @param array $field 提交的数据
     * @return string
     */
    public function curl($url, $field = [])
    {
        //初始化curl
        $ch = curl_init();
        //设置curl参数
        //设置请求地址
        curl_setopt($ch, CURLOPT_URL, $url);
        //设置接收返回结果,但不直接展示在界面
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        //设置禁止证书校验
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        //判断是否为post请求
        if (!empty($field)) {
            //定义超时时间
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
            //开启post请求
            curl_setopt($ch, CURLOPT_POST, 1);
            //传递post数据
            curl_setopt($ch, CURLOPT_POSTFIELDS, $field);
        }

        //发送请求,定义一个变量接收请求结果
        $data = '';
        //发送请求可能失败,所以我需要判断,如果请求成功,将请求结果赋值给$data,反之,不给$data赋值
        if (curl_exec($ch)) {
            $data = curl_multi_getcontent($ch);
        }
        //关闭curl
        curl_close($ch);
        //返回接收到的数据
        return $data;
    }
    /**
     *
     * 1.首先定义请求地址和确定请求方式,向微信端发送获取access_token的请求,会获取到对应的值
     * 2.如果每次都请求,2个小时有效期浪费,我们应该将数据保存到文件中
     * 3.定义保存的目录和文件名称,
     * 4.每次调用方法的时候,首先判断是否存在存放access_token缓存数据的文件,并且该文件是否过期,如果存在并且没过期,直接取值,如果不存在或者过期了,重新获取,然后重新保存
     * 5.最后将access_token的值返回出去
     *
     * @return bool
     */
    public function getAccessToken(){
        //定义缓存目录的地址
        $dir = __DIR__ . '/cache';
        //如果没有就创建一个目录
        is_dir($dir) || mkdir($dir);
        //定义文件名称
        $filename = $dir . '/token_' . md5('wxfde302f8f69ed384') . '.php';
        //每次调用这个方法的时候,就应该判断是否存在存放access_token数据的文件,并且判断这个文件是否过期,如果存在,没有过期的文件,直接从文件里面取值,如果不满足前面的条件,就重新获取,然后保存
        if (is_file($filename) && filemtime($filename) + 7100 > time()){
            //取出$filename的数据
            $data = include $filename;
        }else{
            //设置请求的地址(手册中的token地址appid=测试号的id appsecret=测试的号id下面的)
            $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx33062c92820bd0f0&secret=fde84384a510533f645ce23fc197d00e';
            //使用curl方法发送get请求,获取access_token
            $data = $this->curl($url);
            //如果请求到了结果,判断是否有错,如果有错误,就进行处理,如果没有错误,最后将得到的数据保存起来,然后返回去
            //将得到的数据转成数组,然后进行判断
            $data = json_decode($data,true);
            if (isset($data['errcode'])){
                return false;
            }
            //得到正常的数据,应该将数据写入一个文件
            //将得到的数据写入文件中
            file_put_contents($filename,"<?php return " . var_export($data,true) . ";\n?>");
        }
        //最终将access_token的值返回
        return $data['access_token'];
    }

    /**
     * 获取jsapi_ticket
     * @return bool
     */
    public function getJsApiTicket(){
        //定义缓存目录的地址
        $dir = __DIR__ . '/cache';
        is_dir($dir) || mkdir($dir);
        //定义文件名称
        $filename = $dir . '/ticket_' . md5('wxfde302f8f69ed384') . '.php';
        //判断ticket的文件是否存在,并且没过期,如果存在并没有过期,就直接取文件里面的内容,如果不存在或者过期了,就重新获取然后保存
        if (is_file($filename) && filemtime($filename) + 7100 > time()){
            $data = include $filename;
        }else {
            //设置请求url
            $url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='.$this->getAccessToken(
                ).'&type=jsapi';
            //向url地址发请求
            $data = $this->curl($url);
            $data = json_decode($data, true);
            if ($data['errcode'] != 0) {
                return false;
            } else {
                file_put_contents($filename, '<?php return '.var_export($data, true).";\n?>");
            }
        }
        //将$data中的ticket返回出去
        return $data['ticket'];
    }

}
?>